package com.yonyou.wdt.job;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.yonyou.wdt.dao.MaoerTransferOutDao;
import com.yonyou.wdt.entity.OpenApiURLEnum;
import com.yonyou.wdt.entity.QueryDto;
import com.yonyou.wdt.job.config.BaseConfig;
import com.yonyou.wdt.model.MaoerTransferOutModel;
import com.yonyou.wdt.qimenmodel.qimencloud.api.scenehu3cgwt0tc.request.WdtStockInDtlQueryRequest;
import com.yonyou.wdt.qimenmodel.qimencloud.api.scenehu3cgwt0tc.response.WdtStockInDtlQueryResponse;
import com.yonyou.wdt.service.YonsuiteService;
import com.yonyou.wdt.utils.DateUtils;
import com.yonyou.wdt.utils.WdtClient;
import com.yonyou.wdt.utils.WdtConfigProperties;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

@Component
public class WdtAllocationInToYsAllocationIn extends BaseConfig {
    private static final Logger logger = LoggerFactory.getLogger(WdtAllocationInToYsAllocationIn.class);
    private final WdtConfigProperties configProperties;
    @Resource
    private YonsuiteService yonsuiteService;
    private static final String JOB_CLASS="maoEr018";
    @Resource
    private MaoerTransferOutDao maoerTransferOutDao;
    @Autowired
    public WdtAllocationInToYsAllocationIn(WdtConfigProperties configProperties) {
        this.configProperties = configProperties;
    }
    @XxlJob("WdtAllocationInToYsAllocationIn")
    public ReturnT<String> wdtAllocationInToYsAllocationIn(String params) throws Exception {
        String param = XxlJobHelper.getJobParam();
        Map<String, Object> map = new HashMap<>();
        if (param != null && !"".equals(param)) {
            List<String> timeRange = Arrays.asList(param.split("\\|"));
            if (timeRange.size() == 2) {
                map.put("start_time", timeRange.get(0));
                map.put("end_time", timeRange.get(1));
            } else {
                // 使用单据号同步
                map.put("stockin_no", param);
            }
        } else {
            // 默认查询前一天的数据
            map.put("start_time", DateUtils.getStartDateBy15m());
            map.put("end_time", DateUtils.getStartDateBy10m());
        }
        String dateStr="";
        if (map.get("start_time")!=null && map.get("end_time")!=null) {
            dateStr = map.get("start_time").toString() + map.get("end_time").toString();
        }
        // 处理相关业务
        QueryDto dto = new QueryDto();
        dto.setTenantId(getYsTenantId());
        dto.setAppKey(getYsAppKey());
        dto.setAppSecret(getYsAppSecret());
        // 获取YS系统租户动态域名信息
        ReturnT<String> isReturn2 = getYsDynamicDomainName(JOB_CLASS,dto);
        // 域名获取失败
        if (isReturn2 != null) return isReturn2;
        try {
            // 旺店通调拨入库查询API对象
            List<JSONObject> transferOutList = sendWdt(map);
            // 解析数据，组装YS请求参数
            if (!transferOutList.isEmpty()) {
                ArrayList<Map<String, Object>> ysSaveParamList = new ArrayList<>();
                for (JSONObject jsonObject : transferOutList) {
                    Map<String, Object> ysSaveParam = assembleYsParam(jsonObject, dto);
                    if (null == ysSaveParam) {
                        continue;
                    }
                    ysSaveParamList.add(ysSaveParam);
                }
                logger.info("当前时间段：{}至{}需要同步到YS调拨入库数据有：{}条", map.get("start_time"), map.get("end_time"), ysSaveParamList.size());
                // 调用YS接口保存数据
                int index = 1;
                for (Map<String, Object> paramMap : ysSaveParamList) {
                    JSONObject response = yonsuiteService.transferInSave(paramMap, dto);
                    Map<String, Object> dataMap = (Map<String, Object>) paramMap.get("data");
                    String wdtCode = dataMap.get("code").toString();
                    if (null != response && "200".equals(response.getStr("code"))) {
                        logger.info("旺店通调拨入库：{}保存YS调拨入库成功", wdtCode);
                        InsertLogger(JOB_CLASS,wdtCode, "0", "旺店通调拨入库：{"+wdtCode+"}同步YS调拨入库"+response.getJSONObject("data").getStr("code")+"成功。");
                    } else {
                        if (null != response) {
                            logger.error("旺店通调拨入库：{}保存YS调拨入库失败：{}", dataMap.get("code"), response.getStr("message"));
                            InsertLogger(JOB_CLASS,wdtCode, "0", "旺店通调拨入库：{"+wdtCode+"}同步YS调拨入库失败:"+response.getStr("message"));
                        } else {
                            logger.error("旺店通调拨入库：{}保存YS调拨入库失败，旺店通接口未返回数据", dataMap.get("code"));
                            InsertLogger(JOB_CLASS,wdtCode, "0", "旺店通调拨入库：{"+wdtCode+"}同步YS调拨入库失败:"+response.getStr("message"));
                        }
                    }
                    // 处理YS接口调用频率问题
                 this.APICurrentLimiting(OpenApiURLEnum.TRANSFER_IN_SAVE,59);
                }
            }
        } catch (Exception e) {
            logger.error("Error occurred", e);
            logger.error("旺店通调拨入库同步YS调拨入库失败，{}", e.getMessage());
            InsertLogger(JOB_CLASS,null, "0", dateStr+"旺店通调拨入库同步YS调拨入库失败:"+e.getMessage());
            return ReturnT.FAIL;
        }
        logger.info("  --  旺店通调拨入库同步YS调拨入库任务执行完成  --  ");
        return ReturnT.SUCCESS;
    }


    /**
     * @return
     * @Author Huangwb
     * @Description 组装YS请求数据
     * @Date 14:34 2023/5/17
     * @Param
     **/
    private Map<String, Object> assembleYsParam(JSONObject jsonObject, QueryDto dto) throws Exception {
        // 组装生成调拨
        HashMap<String, Object> inSave = new HashMap<>();
        String wdtCode = jsonObject.getStr("order_no");
        // 查询调拨订单详情查询
        String sourcecode = jsonObject.getStr("src_order_no");
        // 调出列表查询
        MaoerTransferOutModel maoerTransferOutModel = maoerTransferOutDao.queryYsTransferOut(sourcecode);
        if (maoerTransferOutModel==null){
            InsertLogger(JOB_CLASS,sourcecode, "0", "旺店通调拨入库：{"+wdtCode+"}同步YS调拨入库失败:调出单不存在");
            return null;
        }
        sourcecode=maoerTransferOutModel.getYsTransferOutCode();
        List<JSONObject> ysAllOrderList = ysAllInQuery(sourcecode, dto);
        if (ysAllOrderList.isEmpty()){
            InsertLogger(JOB_CLASS,sourcecode, "0", "旺店通调拨入库：{"+wdtCode+"}同步YS调拨入库失败:调出单不存在");
            return null;
        }
        logger.info("获取调出单：", ysAllOrderList);
        inSave.put("mergeSourceData", true);// 是否合并上游数据，固定值为true
        inSave.put("vouchdate", jsonObject.getStr("check_time"));// 单据日期
        inSave.put("bustype", "A07001");// 交易类型id或code
        inSave.put("_status", "Insert");// 操作标识, Insert:新增、Update:更新
        inSave.put("code", wdtCode);// 单据编号 设置手工编号时必输，自动编号时输入无效
        HashMap<String, Object> defMap = new HashMap<>();
        defMap.put("maoer05",wdtCode);
        inSave.put("storeInDefineCharacter",defMap);
        // 以旺店通的数量为主
        JSONArray detailList = jsonObject.getJSONArray("details_list");
        JSONArray dateIlsList = new JSONArray();
        for (int i = 0; i < detailList.size(); i++) {
            JSONObject goodJSONObject = JSONUtil.parseObj(detailList.get(i));
            for (JSONObject ysAllOrderJSONObject : ysAllOrderList) {
                if (goodJSONObject.getStr("goods_no").equals(ysAllOrderJSONObject.getStr("product_cCode"))){
                    HashMap<String, Object> dateIls = new HashMap<>();
                    dateIls.put("_status", "Insert");// 操作标识, Insert:新增、Update:
                    dateIls.put("sourceid", ysAllOrderJSONObject.getStr("id"));// 上游单据主表id
                    dateIls.put("sourceautoid", ysAllOrderJSONObject.getStr("details_id"));// 上游单据子表id
                    dateIls.put("makeRuleCode","storeoutTostorein");
                    dateIls.put("qty", goodJSONObject.getBigDecimal("num"));// 数量
                    dateIls.put("batchno", StringUtils.isBlank(goodJSONObject.getStr("batch"))?"202412":goodJSONObject.getStr("batch"));
                    dateIls.put("invaliddate", StringUtils.isBlank(goodJSONObject.getStr("expire_date"))  || goodJSONObject.getStr("expire_date").substring(0,10).equals("0000-00-00")?"2027-12-31":goodJSONObject.getStr("expire_date"));

                    dateIlsList.add(dateIls);
                }
            }
        }
        inSave.put("details", dateIlsList);
        JSONObject queryData = new JSONObject();
        queryData.put("data", inSave);
        return queryData;
    }

    private List<JSONObject> ysAllInQuery(String sourcecode, QueryDto dto) throws Exception {
        HashMap<String, Object> purOrderReqMap = new HashMap<>();
        Integer pageSize = 200;
        purOrderReqMap.put("pageIndex", 1);
        purOrderReqMap.put("pageSize", pageSize);
        purOrderReqMap.put("code", sourcecode);
        List<JSONObject> objects = new ArrayList<>();
        Boolean hasNext = true;
        while (hasNext) {
            JSONObject ysPurList = yonsuiteService.transferOutList(purOrderReqMap, dto);
            Integer pageIndex = Integer.valueOf(purOrderReqMap.get("pageIndex").toString());
            if (ysPurList.getStr("code") != null && "200".equals(ysPurList.getStr("code")) && hasNext) {
                Integer totalCount = 0;
                if (totalCount == 0 && ysPurList.getJSONObject("data").getInt("recordCount") != 0) {
                    totalCount = ysPurList.getJSONObject("data").getInt("recordCount");
                } else {
                    return objects;
                }
                int pageCount = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
                JSONArray jsonArray = ysPurList.getJSONObject("data").getJSONArray("recordList");
                List<JSONObject> list = JSONUtil.toList(jsonArray,JSONObject.class);
                objects.addAll(list);
                purOrderReqMap.put("pageIndex", pageIndex + 1);
                if (pageIndex == pageCount) {
                    hasNext = false;
                }
            } else {
                hasNext = false;
            }
            this.APICurrentLimiting(OpenApiURLEnum.TRANSFER_OUTWARE_LIST_QUERY,60);
        }
        return objects;
    }


    /**
     * @return
     * @Author Huangwb
     * @Description 发送请求查询旺店通数据
     * @Date 19:03 2023/5/12
     * @Param
     **/
    private List<JSONObject> sendWdt(Map<String, Object> map){
        // 创建旺店通采购入库单查询请求实体对象
        // 单据状态：10=已取消；20=编辑中；30=待审核；37=待质检；40=质检确认；80=已完成
        Byte status = 80;
        //单据类别 1采购入库, 2调拨入库,  4盘盈入库, 5生产入库, 6调拨入库, 7保修入库, 8纠错入库, 9初始化入库 10 预入库 11 JIT退货入库 12 委外入库
        map.put("order_type",2);
        map.put("status",status);
        //otherInStockRequest.setOrder_type(type);
        int pageSize = 50;
        int pageIndex = 0;
        List<JSONObject> transferInList = new ArrayList<>();
        // 旺店通请求客户端对象创建
        WdtClient client = new WdtClient(configProperties.getSid(), configProperties.getKey(), configProperties.getSecret(), configProperties.getUrl());

        // 循环查询满足条件的所有数据
        while (true) {
            map.put("page_no",pageIndex);
            map.put("page_size",pageSize);
            // 调用旺店通接口查询调拨入库单数据
            String execute = client.execute("stockin_order_query.php", map);
            cn.hutool.json.JSONObject response = JSONUtil.parseObj(execute);
            if (null != response && response.getInt("code") == 0) {
                int totalCount = response.getInt("total_count");
                // 旺店通接口查询频率问题处理
                JSONArray jsonArray = response.getJSONArray("stockin_list");
                if (!jsonArray.isEmpty()){
                    List<JSONObject> list = JSONUtil.toList(jsonArray, JSONObject.class);
                        com.yonyou.wdt.qimenmodel.qimencloud.api.DefaultQimenCloudClient qmClient = new com.yonyou.wdt.qimenmodel.qimencloud.api.DefaultQimenCloudClient(configProperties.getQmServerUrl(), configProperties.getQmAppKey(), configProperties.getQmAppSecret(), "json");

                        //resList.addAll(JSONUtil.toList(orderArray, JSONObject.class));
                        for (JSONObject entries : list) {
                            ArrayList<JSONObject> dtlList = new ArrayList<>();
                            HashMap<String, Object> stringObjectHashMap = new HashMap<>();
                            String stockOutNo = entries.getStr("order_no");
                            stringObjectHashMap.put("stockin_no",stockOutNo);
                            Boolean flag=true;
                            Integer dtlTotalCount=0;
                            Integer dtlTotalPage=0;
                            Integer dtlRealityPageNo = 0;
                            while (flag){
                                stringObjectHashMap.put("page_no",dtlRealityPageNo.toString());
                                stringObjectHashMap.put("page_size",100);
                                WdtStockInDtlQueryRequest dtlReq = this.setStockInDtlModel(stringObjectHashMap, configProperties.getQmTargetAppKey(), configProperties.getSid());
                                WdtStockInDtlQueryResponse dtlRes = null;
                                try {
                                    dtlRes = qmClient.execute(dtlReq);
                                } catch (com.yonyou.wdt.qimenmodel.taobao.api.ApiException e) {
                                    throw new RuntimeException(e);
                                }
                                JSONObject dtlJson = JSONUtil.parseObj(dtlRes.getBody()).getJSONObject("response");
                                if ("0".equals(dtlJson.getStr("errorcode"))) {
                                    //判断分页
                                    if (dtlRealityPageNo == 0) {
                                        dtlTotalCount = dtlJson.getInt("total_count", 0);
                                        dtlTotalPage = dtlTotalCount % 100 == 0 ? dtlTotalCount / 100 : dtlTotalCount / 100 + 1;
                                    }
                                    //每页订单列表
                                    JSONArray dtlJosn = dtlJson.getJSONArray("stockin_batch_detail");
                                    dtlList.addAll(JSONUtil.toList(dtlJosn,JSONObject.class));
                                }else {
                                    InsertLogger(JOB_CLASS,stockOutNo, "0", "旺店通入库批次接口查询失败" + dtlJson.getStr("message"));
                                    break;
                                }
                                this.APICurrentLimiting("wdt.stockin.batch.detail",59);
                                if (dtlTotalPage > dtlRealityPageNo + 1) {
                                    dtlRealityPageNo += 1;
                                } else {
                                    flag = false;
                                }
                            }


                            JSONArray dtljsonArray = entries.getJSONArray("details_list");
                            JSONArray newDetail = new JSONArray();
                            for (Object obj : dtljsonArray) {
                                JSONObject entries1 = JSONUtil.parseObj(obj);
                                Optional<JSONObject> any = dtlList.stream().filter(o -> o.getStr("goods_no").equals(entries1.getStr("goods_no"))).findAny();
                                if (any.isPresent()){
                                    entries1.set("batch",any.get().getStr("batch"));
                                    String substring = any.get().getStr("expire_date").substring(0, 10);
                                    if (!substring.equals("0000-00-00")){
                                        entries1.set("expire_date", substring);
                                    }else {
                                        entries1.set("expire_date", "");
                                    }
                                }

                                newDetail.add(entries1);
                            }
                            entries.set("details_list",newDetail);
                            transferInList.add(entries);
                    }
                }
                Integer page=pageIndex+1;
                if (totalCount < page * pageSize) {
                    break;
                } else {
                    pageIndex++;
                }
            } else {
                if (response != null) {
                    logger.error("查询旺店通调拨入库单异常：{}，请重试", response.getStr("message"));
                    return null;
                } else {
                    logger.error("查询旺店通调拨入库单异常：旺店通接口返回数据为空，请重试");
                    return null;
                }
            }
            this.APICurrentLimiting("stockin_order_query.php",59);

        }
        logger.info("当前时间段：【{}】-【{}】旺店通调拨入库单共有：【{}】条", map.get("start_time"), map.get("end_time"), transferInList.size());
        return transferInList;
    }

}
